package cn.fulong.smebj.admin.util;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import java.io.*;
import java.util.*;

/**
 * @Description:
 */
public class FileUtil {
    private static Timer timer = new Timer();

    public static String getProjectPath() {
        return new ApplicationHome(FileUtil.class).getSource().getParentFile().toString();
    }

    /**
     * 创建文件，可选择是否覆盖旧文件
     * @return file
     */
    public static File createFile(String filePath, boolean cover) {
        try {
            // 保证创建一个新文件
            File file = new File(filePath);
            // 如果父目录不存在，创建父目录
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }

            //覆盖旧文件
            if (cover) {
                // 如果已存在，删除文件
                if (file.exists()) {
                    file.delete();
                }
            }

            // 如果文件不存在，则创建文件
            if (!file.exists()) {
                file.createNewFile();
            }

            return file;
        } catch (IOException e) {
            throw new RuntimeException("创建文件失败，原因" + e.getMessage());
        }
    }

    /**
     * 获取文件，可配置如果文件不存在是否创建新文件
     * @param filePath filePath
     * @return file
     */
    public static File getFile(String filePath, boolean autoCreate) {
        File file = new File(filePath);
        if (autoCreate) {
            // 如果父目录不存在，创建父目录
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            // 如果文件不存在，则创建文件
            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new RuntimeException("创建文件失败，原因" + e.getMessage());
                }
            }
        } else {
            // 如果父目录不存在，则抛出异常
            if (!file.getParentFile().exists()) {
                throw new RuntimeException("父目录不存在");
            }
            // 如果文件不存在，则抛出异常
            if (!file.exists()) {
                throw new RuntimeException("文件不存在");
            }
        }

        return file;
    }

    /**
     * 定时删除文件
     * @param millisecondValue 时间戳
     */
    public static void deleteFileOnTime(String filePath, long millisecondValue) {
        File file = new File(filePath);
        if (!file.exists()) {
            return;
        }
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                delteFile(file);
            }
            //递归删除文件及文件夹
            private void delteFile(File file) {
                if (file.isFile()) {
                    file.delete();
                    return;
                }
                File[] filearray = file.listFiles();
                if (filearray != null) {
                    for (File f : filearray) {
                        if (f.isDirectory()) {
                            delteFile(f);
                        } else {
                            f.delete();
                        }
                    }
                    file.delete();
                }
            }
        }, new Date(System.currentTimeMillis()+millisecondValue));
    }

    /**
     * 将json写入文件
     * @param filePath 文件路径
     * @param json 待写入json
     */
    public static void jsonWriteFile(String filePath, JSONObject json, boolean append) {
        textWriteFile(getFile(filePath, true), json.toJSONString(), append);
    }

    /**
     * 将text写入文件
     * @param filePath 文件路径
     * @param text 待写入text
     */
    public static void textWriteFile(String filePath, String text, boolean append) {
        textWriteFile(getFile(filePath, true), text, append);
    }

    /**
     * 将text写入文件
     * @param file 文件
     * @param text 待写入text
     */
    public static void textWriteFile(File file, String text, boolean append) {
        Writer writer = null;
        try {
            // GB2312 写cvs时候使用
            writer = new OutputStreamWriter(
                    new FileOutputStream(file, append),
                    "UTF-8"
            );
            writer.write(text + "\r\n");
            writer.flush();
        } catch (IOException e) {
            throw new RuntimeException("写入文件失败，原因" + e.getMessage());
        } finally {
            if (null != writer) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 读取文件，如果文件不存在，则抛出异常
     * @param file 文件路径
     * @return 文件内容
     */
    public static String readFile(File file) {
        StringBuilder sb = new StringBuilder();
        BufferedReader br = null;
        try {
            if (null == file) {
                throw new RuntimeException("file不能为空");
            }
            if (!file.exists() || !file.isFile()) {
                throw new RuntimeException("file不存在");
            }
            br = new BufferedReader(new FileReader(file));
            String line = "";
            while ((line = br.readLine()) != null) {
                sb.append(line).append("\r\n");
            }
        } catch (Exception e) {
            throw new RuntimeException("读取文件失败，原因" + e.getMessage());
        } finally {
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return sb.toString();
    }

    /**
     * 读取文件，如果文件不存在，则抛出异常
     * @param file 文件路径
     * @return 文件内容
     */
    public static List<String> readFileToList(File file) {
        List<String> result = new ArrayList<>();
        BufferedReader br = null;
        try {
            if (null == file) {
                throw new RuntimeException("file不能为空");
            }
            if (!file.exists() || !file.isFile()) {
                throw new RuntimeException("file不存在");
            }
            br = new BufferedReader(new FileReader(file));
            String line = "";
            while ((line = br.readLine()) != null) {
                result.add(line.trim());
            }
        } catch (Exception e) {
            throw new RuntimeException("读取文件失败，原因" + e.getMessage());
        } finally {
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return result;
    }

    /**
     * file是否包含text
     * @param file 文件
     * @param text text
     * @return 是否包含true or false
     */
    public static boolean containText(File file, String text) {
        StringBuilder sb = new StringBuilder();
        BufferedReader br = null;
        try {
            if (null == file) {
                throw new RuntimeException("file不能为空");
            }
            if (!file.exists() || !file.isFile()) {
                throw new RuntimeException("file不存在");
            }
            br = new BufferedReader(new FileReader(file));
            String line = "";
            int size = 0;
            while ((line = br.readLine()) != null) {
                if (100 == size) {
                    if (sb.toString().contains(text)) {
                        return true;
                    }
                    sb = new StringBuilder();
                    size = 0;
                }
                sb.append(line).append("\r\n");
                size++;
            }
            if (sb.toString().contains(text)) {
                return true;
            }
            return false;
        } catch (Exception e) {
            throw new RuntimeException("读取文件失败，原因" + e.getMessage());
        } finally {
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * file是否包含text
     * @param file 文件
     * @param line line
     * @return 是否包含true or false
     */
    public static boolean containLine(File file, String line) {
        BufferedReader br = null;
        try {
            if (StringUtils.isEmpty(line)) {
                throw new RuntimeException("line不能为空");
            }
            if (null == file) {
                throw new RuntimeException("file不能为空");
            }
            if (!file.exists() || !file.isFile()) {
                throw new RuntimeException("file不存在");
            }
            br = new BufferedReader(new FileReader(file));
            String currentLine = "";
            while ((currentLine = br.readLine()) != null) {
                if (line.equals(currentLine)) {
                    return true;
                }
            }
            return false;
        } catch (Exception e) {
            throw new RuntimeException("读取文件失败，原因" + e.getMessage());
        } finally {
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 读取文件，如果文件不存在，则抛出异常
     * @param filePath 文件路径
     * @return 文件内容
     */
    public static String readFile(String filePath) {
        if (StringUtils.isEmpty(filePath)) {
            throw new RuntimeException("filePath不能为空");
        }
        return readFile(new File(filePath));
    }

    /**
     * 获取文件指定行数的数据，用于爬虫获取当前要爬的链接
     * @param filePath  目标文件
     * @param point   指针
     */
    public String getFileLine(String filePath, long point) {
        String thisLine = "";
        long thisNum = 0;
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(FileUtil.getFile(filePath, false)));
            while ((thisLine = reader.readLine()) != null) {
                if(point == thisNum) {
                    return thisLine;
                }
                thisNum++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != reader) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return thisLine;
    }

    /**
     * 获取文件总行数（有多少链接）
     * @param filePath  文件路径
     * @return  总行数
     */
    public static long getFileCount(String filePath) {
        long count = 0;
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(FileUtil.getFile(filePath, false)));
            while (!StringUtils.isEmpty(reader.readLine())) {
                count++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != reader) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return count;
    }

    /**
     * 读取resource文件
     * @param rec resource
     * @return string
     */
    public static String readResource(String rec) {
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();
        try {
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            Resource resource = resolver.getResource(rec);
            br = new BufferedReader(new InputStreamReader(resource.getInputStream()));
            String line = null;
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
            try {
                assert br != null;
                br.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
        return sb.toString();
    }
}